<!--
 * @Description:会动的词云
 * @Author: Vergil
 * @Date: 2021-08-25 14:17:45
 * @LastEditTime: 2021-08-25 17:08:15
 * @LastEditors: Vergil
-->
<template>
  <div class="wordCloud" ref="wordCloud"></div>
</template>
<script>
  export default {
    name: "word-cloud",
    data() {
      return {
        hotWord: [
          "万事如意",
          "事事如意 ",
          "万事亨通",
          "一帆风顺",
          "万事大吉",
          "吉祥如意",
          "步步高升",
          "步步登高",
          "三羊开泰",
          "得心应手",
          "财源广进",
          "陶未媲美",
          "阖家安康",
          "龙马精神",
          "锦绣前程",
          "吉祥如意",
          "生龙活虎",
          "神采奕奕",
          "五谷丰登",
          "马到成功",
          "飞黄腾达",
          " 步步高升",
          "福禄寿禧"
        ],
        color: ["#a18cd1", "#fad0c4", "#ff8177", "#fecfef", "#fda085", "#f5576c", "#fe9a8b", "#30cfd0", "#38f9d7"],
        wordArr: [],
        timer: null,
        resetTime: 10,
        ContainerSize: ""
      };
    },
    mounted() {
      this.init();
    },
    methods: {
      init() {
        this.dealSpan();
        this.initWordPos();
        this.render();
      },
      dealSpan() {
        const wordArr = [];
        this.hotWord.forEach(value => {
          // 根据词云数量生成span数量设置字体颜色和大小
          const spanDom = document.createElement("span");
          spanDom.style.position = "relative";
          spanDom.style.display = "inline-block";
          spanDom.style.color = this.randomColor();
          spanDom.style.fontSize = this.randomNumber(35, 40) + "px";
          spanDom.innerHTML = value;
          spanDom.local = {
            position: {
              // 位置
              x: 0,
              y: 0
            },
            direction: {
              // 方向 正数往右 负数往左
              x: 1,
              y: 1
            },
            velocity: {
              // 每次位移初速度
              x: -0.5 + Math.random(),
              y: -0.5 + Math.random()
            }
          };
          this.$refs.wordCloud.appendChild(spanDom);
          wordArr.push(spanDom);
        });
        this.wordArr = wordArr;
      },
      randomColor() {
        // 获取随机颜色
        var colorIndex = Math.floor(this.color.length * Math.random());
        return this.color[colorIndex];
      },
      randomNumber(lowerInteger, upperInteger) {
        // 获得一个包含最小值和最大值之间的随机数。
        const choices = upperInteger - lowerInteger + 1;
        return Math.floor(Math.random() * choices + lowerInteger);
      },
      render() {
        if (this.resetTime < 100) {
          this.resetTime = this.resetTime + 1;
          this.timer = requestAnimationFrame(this.render.bind(this));
          this.resetTime = 0;
        }
        this.wordFly();
      },
      wordFly() {
        this.wordArr.forEach(value => {
          // 设置运动方向 大于边界或者小于边界的时候换方向
          if (
            value.local.realPos.minx + value.local.position.x < this.ContainerSize.leftPos.x ||
            value.local.realPos.maxx + value.local.position.x > this.ContainerSize.rightPos.x
          )
            value.local.direction.x = -value.local.direction.x;
          if (
            value.local.realPos.miny + value.local.position.y < this.ContainerSize.leftPos.y ||
            value.local.realPos.maxy + value.local.position.y > this.ContainerSize.rightPos.y
          )
            value.local.direction.y = -value.local.direction.y;
          value.local.position.x += value.local.velocity.x * value.local.direction.x;
          value.local.position.y += value.local.velocity.y * value.local.direction.y;
          // 给每个词云加动画过渡
          value.style.transform =
            "translateX(" + value.local.position.x + "px) translateY(" + value.local.position.y + "px)";
        });
      },
      initWordPos() {
        // 计算每个词的真实位置和容器的位置
        this.wordArr.forEach(value => {
          value.local.realPos = {
            minx: value.offsetLeft,
            maxx: value.offsetLeft + value.offsetWidth,
            miny: value.offsetTop,
            maxy: value.offsetTop + value.offsetHeight
          };
        });
        this.ContainerSize = this.getContainerSize();
      },
      getContainerSize() {
        // 判断容器大小控制词云位置
        const el = this.$refs.wordCloud;
        return {
          leftPos: {
            // 容器左侧的位置和顶部位置
            x: el.offsetLeft,
            y: el.offsetTop
          },
          rightPos: {
            // 容器右侧的位置和底部位置
            x: el.offsetLeft + el.offsetWidth,
            y: el.offsetTop + el.offsetHeight
          }
        };
      }
    },
    destroyed() {
      // 组件销毁，关闭定时执行
      cancelAnimationFrame(this.timer);
    }
  };
</script>
<style lang="less" scoped>
  .wordCloud {
    width: 500px;
    height: 500px;
  }
</style>
